package org.mapdroid.maps.gmaps.overlay;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.mapdroid.maps.gmaps.MdMapActivity;
import org.mapdroid.maps.gmaps.MdMapView;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.Vibrator;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.OnGestureListener;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class MdRouteOverlay extends Overlay implements OnGestureListener{
	private GeoPoint startPoint;
	private GeoPoint endPoint;
	private MdMapView mapView;
	private int mRadius=6;
	private String path;
	private List<GeoPoint> points;
	private GestureDetector gestureDetector;
	private Vibrator vibrator;

	public MdRouteOverlay(Context context, MdMapView mapView, GeoPoint gp1, GeoPoint gp2){ 
		super();
		this.mapView = mapView;
		this.startPoint = gp1;
		this.endPoint = gp2;
		this.points = null;
		
		gestureDetector = new GestureDetector(this);
		this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
	}

	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow){
		//super.draw(canvas, mapView, shadow);
		if(points == null)
			return; 
		
		GeoPoint tmpStartPoint;
		GeoPoint tmpEndPoint;
		Point point1 = new Point();
		Point point2 = new Point();
		
		Paint paint = new Paint();		
		paint.setAntiAlias(true);
		paint.setColor(Color.BLUE);
		
		tmpEndPoint = points.get(0);
		tmpStartPoint = tmpEndPoint;
		Projection projection = mapView.getProjection();
		projection.toPixels(tmpEndPoint, point2);
		
		RectF oval=new RectF(	point2.x - mRadius, point2.y - mRadius,
								point2.x + mRadius, point2.y + mRadius);
		// start point
		canvas.drawOval(oval, paint);
		
		paint.setColor(Color.GREEN);
		paint.setStrokeWidth(5);
		paint.setAlpha(120);
		
		int size = points.size();
		for(int i=0;i<size-1;i++){ // the last one would be crash
			tmpStartPoint=points.get(i);
			tmpEndPoint = points.get(i+1);
			projection.toPixels(tmpStartPoint, point1);
			projection.toPixels(tmpEndPoint, point2);
			canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint);
		}

		tmpEndPoint = points.get(points.size()-1);
		paint.setColor(Color.RED);
		projection.toPixels(tmpEndPoint, point2);
		RectF oval2=new RectF(	point2.x - mRadius, point2.y - mRadius,
								point2.x + mRadius, point2.y + mRadius);
		/* end point */
		paint.setAlpha(255);
		canvas.drawOval(oval2, paint);
		return;
	}
	
	public void calculatePath() throws MalformedURLException, IOException, ParserConfigurationException, SAXException{
		// connect to map web service
		StringBuilder urlString = new StringBuilder();
		urlString.append("http://maps.google.com/maps?f=d&hl=en");
		urlString.append("&saddr=");//from
		urlString.append( Double.toString((double)startPoint.getLatitudeE6()/1.0E6 ));
		urlString.append(",");
		urlString.append( Double.toString((double)startPoint.getLongitudeE6()/1.0E6 ));
		urlString.append("&daddr=");//to
		urlString.append( Double.toString((double)endPoint.getLatitudeE6()/1.0E6 ));
		urlString.append(",");
		urlString.append( Double.toString((double)endPoint.getLongitudeE6()/1.0E6 ));
		urlString.append("&ie=UTF8&0&om=0&output=kml");
		//Log.d("xxx","URL="+urlString.toString());
		// get the kml (XML) doc. And parse it to get the coordinates(direction route).
		Document doc = null;
		HttpURLConnection urlConnection= null;
		URL url = null;
	
		url = new URL(urlString.toString());
		try{
			urlConnection=(HttpURLConnection)url.openConnection();
			urlConnection.setRequestMethod("GET");
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			urlConnection.connect();
		}
		catch(IOException e){
			points = null;
			throw e;
		}
	
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		doc = db.parse(urlConnection.getInputStream());
	
		if(doc.getElementsByTagName("GeometryCollection").getLength()>0){
			//String path = doc.getElementsByTagName("GeometryCollection").item(0).getFirstChild().getFirstChild().getNodeName();
			path = doc.getElementsByTagName("GeometryCollection").item(0).getFirstChild().getFirstChild().getFirstChild().getNodeValue();
			points = new LinkedList<GeoPoint>();
			String[] pairs = path.split(" ");
			//Point tmpPoint = new Point();
			GeoPoint tmpGeoPoint;
			for(int i=0; i<pairs.length; i++){
				String[] lngLat = pairs[i].split(",");
				try{
					tmpGeoPoint=new GeoPoint((int)(Double.parseDouble(lngLat[1])*1E6),(int)(Double.parseDouble(lngLat[0])*1E6));
					//mapView.getProjection().toPixels(tmpGeoPoint, tmpPoint);
					points.add(tmpGeoPoint);
				}catch(NumberFormatException e){
					e.printStackTrace();
				}
			}
			
			//Log.d("xxx","path="+ path);
			//draw(canvas, mapView, false);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent e, MapView mapView){
		gestureDetector.onTouchEvent(e);
		this.mapView.hasEventHandled(true);
		return false;
	}
	
	@Override
	public boolean onDown(MotionEvent arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
			float arg3) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onLongPress(MotionEvent arg0) {
		// TODO Auto-generated method stub
		vibrator.vibrate(75);
		MdMapActivity.removeDirectionDialog.show();
	}

	@Override
	public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
			float arg3) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean onSingleTapUp(MotionEvent arg0) {
		// TODO Auto-generated method stub
		return false;
	}	
}